package com.tb.sng.utils.loader
{
	import com.adobe.serialization.json.JSON;
	import com.adobe.serialization.json.JSONParseError;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.Dictionary;

	/**
	 * 数据获取类
	 * 支持http协议的数据获取
	 * 单例类
	 * @author 任冬 rendong01@snda.com
	 */
	public class HttpLoader
	{
		/**
		 * 加载失败的保存日志的url地址
		 */		
		private static var LOGPATH:String = null;
		

		/**
		 * 设置过滤器函数
		 * */
		public static function setFilterFun(fun:Function):void
		{
			_filterFun = fun;
		}

		/**
		 * 如果json处理错误，则会调用该方法，并把结果以jsondata返回 
		 */		
		private static var jsonErrorHandler:Function = HttpLoader.defaultJsonErrorHander;
		
		/**
		 * 错误提示信息 
		 */		
		private static var jsonErrorMessage:String = 'json 解析错误：';
		private static var ioErrorMessage:String = '网络io错误，请检查网络连接!';
		private static var securityErrorMessage:String = '安全问题，请检查crossdomain.xml';
		
		/**
		 * 存储 httpData方法调用的参数
		 */		
		private var _httpDataDict:Dictionary = new Dictionary();
		
		/**过滤函数* */
		private static var _filterFun:Function;
		
		/**
		 * 创建唯一实例 
		 */		
		private static var _instance:HttpLoader = new HttpLoader();
		
		public function HttpLoader()
		{
			if (_instance)
				throw new Error("Create HttpData Instance Error");
		}
		
		
		/**
		 * 如果json处理错误，则会调用该方法，并把结果以jsondata返回 
		 *  
		 * @param handler
		 * 
		 */		
		public static function setJsonErrorHandler(handler:Function):void
		{
			jsonErrorHandler = handler;
		}
		
		/**
		 * 设置记录解析错误的地址
		 * 请求为post格式，参数为：Url,Msg
		 *  
		 * @param url
		 * 
		 */		
		public static function setLogUrl(url:String):void
		{
			LOGPATH = url;
		}
		
		/**
		 * 设置错误处理 国际化语言 
		 * @param jsonErrorMessage	json 解析错误：
		 * @param ioErrorMessage	网络io错误，请检查网络连接!
		 * @param securityErrorMessage	安全问题，请检查crossdomain.xml
		 * 
		 */		
		public static function setErrorMessage(jsonErrorMessage:String, ioErrorMessage:String, securityErrorMessage:String):void
		{
			HttpLoader.jsonErrorMessage = jsonErrorMessage;
			HttpLoader.ioErrorMessage = ioErrorMessage;
			HttpLoader.securityErrorMessage = securityErrorMessage;
		}
		
		/**
		 * 默认的json错误处理 
		 * @param message
		 * @return 
		 * 
		 */		
		private static function defaultJsonErrorHander(message:String):Object
		{
			var result:Object = {};
			result.status = 0;
			result.message = message;
			
			return result;
		}
		
		/**
		 * 获取http Text数据
		 * 
		 * @param	url	请求地址
		 * @param	callback	请求成功的回调方法，参数为：loader.data
		 * @param	vars	附加的请求变量
		 * @param   errorCallback 加载失败回调函数，参数：string
		 * @param	method	请求的方法
		 * @param 	dataFormat	加载数据格式
		 * @return void
		 */
		public static function httpData(url:String, successCallback:Function = null, vars:URLVariables = null, errorCallback:Function = null, method:String= null, dataFormat:String="text"):void
		{
			_instance._httpData(url, successCallback, vars, errorCallback, method, dataFormat);
		}
	
		/**
		 * 获取http json数据
		 * 
		 * @param	url	请求地址
		 * @param	callback	请求成功的回调方法，参数为：jsondata
		 * @param	vars	附加的请求变量
		 * @param   errorCallback 加载失败回调函数,参数为：string
		 * @param	method	请求的方法
		 * @param 	dataFormat	加载数据格式
		 * @return void
		 */
		public static function httpJson(url:String, successCallback:Function = null, vars:URLVariables = null, method:String= null):void
		{
			_instance._httpJson(url, successCallback, vars, method);
		}
		
		
		
		// httpJson 的真实请求
		public function _httpJson( url:String, successCallback:Function = null, vars:URLVariables = null, method:String= null, dataFormat:String="text"):void
		{
			var successFunc:Function = function (result:String):void
			{
				var stre:String = result as String;
				var obj:Object=null;
				try {
					obj = com.adobe.serialization.json.JSON.decode(stre);
					//加载过滤器
					if(_filterFun != null)
						_filterFun(obj);
					
				}catch (e:JSONParseError) {
					httpLog(url, HttpLoader.jsonErrorMessage + e);
					successCallback(jsonErrorHandler(HttpLoader.jsonErrorMessage + e));
				}
				
				if (successCallback != null && obj != null)
					successCallback(obj);
			};
			
			_httpData(url, successFunc, vars, function (message:String):void{
				successFunc(jsonErrorHandler(message));
			}, method, dataFormat);
		}
				
		// 真实请求
		public function _httpData( url:String, successCallback:Function = null, vars:URLVariables = null, errorCallback:Function = null, method:String= null, dataFormat:String="text"):void
		{
			var param:httpDataParam = new httpDataParam();
			param.url = url;
			param.successCallback = successCallback;
			param.vars = vars;
			param.errorCallback = errorCallback;
			param.method = method;
			param.dataFormat = dataFormat;
			
			var loader:URLLoader = new URLLoader();
			_httpDataDict[loader] = param;
			
			loader.addEventListener(Event.COMPLETE, httpCompleteHandler);
			loader.addEventListener(IOErrorEvent.IO_ERROR, httpIoErrorHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, httpSecurityErrorHandler);
			
			// 当地址里面已经有“?”号时，flash不会自动在已有变量后加&
			if (vars != null && vars.toString().length != 0 && url.lastIndexOf("?") != -1 && method != URLRequestMethod.POST)
				url += "&";
			
			var req:URLRequest = new URLRequest(url);
			
			if (method != null)
				req.method = method;
			
			loader.dataFormat = dataFormat;
			
			if (vars != null)
				req.data = vars;
			
			loader.load(req);
		}
		
		// 加载完成
		private function httpCompleteHandler(e:Event):void
		{
			var loader:URLLoader = e.target as URLLoader;
			var param:httpDataParam = _httpDataDict[loader];
			
			trace("httpData success", param.url, param.vars);
			
			if (param != null && param.successCallback != null)
				param.successCallback(loader.data);
			
			delete _httpDataDict[loader];
		}
		
		// 加载io错误
		private function httpIoErrorHandler(e:IOErrorEvent):void
		{
			var loader:URLLoader = e.target as URLLoader;
			var param:httpDataParam = _httpDataDict[loader];
			
			trace ("httpData IoError:", param.url, e);
			
			if (param.errorCallback != null)
				param.errorCallback(HttpLoader.ioErrorMessage);
			
			httpLog(param.url, e.toString());
			
			delete _httpDataDict[loader];
		}
		
		// 加载安全错误
		private function httpSecurityErrorHandler(e:SecurityErrorEvent):void
		{
			var loader:URLLoader = e.target as URLLoader;
			var param:httpDataParam = _httpDataDict[loader];
			
			trace ("httpData SecurityError:", param.url, e);
			
			if (param.errorCallback != null)
				param.errorCallback(HttpLoader.securityErrorMessage);
			
			httpLog(param.url, e.toString());
			
			delete _httpDataDict[loader];
		}
		
		/**
		 * 客户端发送错误日志到服务器端
		 * @param	urlqqq
		 * @param	msg
		 */
		public function httpLog( url:String, msg:String):void
		{
			if (LOGPATH == null){
				return;
			}
			
			var loader:URLLoader = new URLLoader();
			var req:URLRequest = new URLRequest();
			req.url = LOGPATH;
			
			loader.addEventListener(Event.COMPLETE, ignoreEvent);
			loader.addEventListener(IOErrorEvent.IO_ERROR, ignoreEvent);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, ignoreEvent);
			
			var vars:URLVariables = new URLVariables();
			vars.Url = url;
			vars.Msg = msg;
			
			req.data = vars;
			
			req.method = URLRequestMethod.POST;
			
			loader.load(req);
		}
		
		/**
		 * 忽略事件
		 * @param	e
		 */
		private function ignoreEvent(e:Event):void
		{
			// ignore
		}
	}
}

import flash.net.URLVariables;

/**
 * httpdata参数 
 * @author rendong01
 * 
 */	
class httpDataParam{
	public var url:String;
	public var successCallback:Function;
	public var vars:URLVariables;
	public var errorCallback:Function;
	public var method:String;
	public var dataFormat:String;
}